package leetcode;

/*
332. 重新安排行程
给定一个机票的字符串二维数组 [from, to]，子数组中的两个成员分别表示飞机出发和降落的机场地点，对该行程进行重新规划排序。所有这些机票都属于一个从 JFK（肯尼迪国际机场）出发的先生，所以该行程必须从 JFK 开始。
说明:
如果存在多种有效的行程，你可以按字符自然排序返回最小的行程组合。例如，行程 ["JFK", "LGA"] 与 ["JFK", "LGB"] 相比就更小，排序更靠前
所有的机场都用三个大写字母表示（机场代码）。
假定所有机票至少存在一种合理的行程。
示例 1:
输入: [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]
输出: ["JFK", "MUC", "LHR", "SFO", "SJC"]
示例 2:
输入: [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
输出: ["JFK","ATL","JFK","SFO","ATL","SFO"]
解释: 另一种有效的行程是 ["JFK","SFO","ATL","JFK","ATL","SFO"]。但是它自然排序更大更靠后。
*/

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;

public class problems_331 {
    public static void main(String[] args) {
        List<List<String>> tickets = new ArrayList<List<String>>();
        tickets.add(new ArrayList<String>() {{add("JFK");add("SFO");}});
        tickets.add(new ArrayList<String>() {{add("JFK");add("ATL");}});
        tickets.add(new ArrayList<String>() {{add("SFO");add("ATL");}});
        tickets.add(new ArrayList<String>() {{add("ATL");add("JFK");}});
        tickets.add(new ArrayList<String>() {{add("ATL");add("SFO");}});


//        tickets.add(new ArrayList<String>() {{add("AXA");add("EZE");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("AUA");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("JFK");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("TIA");}});
//        tickets.add(new ArrayList<String>() {{add("AUA");add("AXA");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("TIA");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("TIA");}});
//        tickets.add(new ArrayList<String>() {{add("AXA");add("EZE");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("ANU");add("EZE");}});
//        tickets.add(new ArrayList<String>() {{add("TIA");add("EZE");}});
//        tickets.add(new ArrayList<String>() {{add("JFK");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("AUA");add("JFK");}});
//        tickets.add(new ArrayList<String>() {{add("JFK");add("EZE");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("ANU");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("AUA");}});
//        tickets.add(new ArrayList<String>() {{add("ANU");add("AXA");}});
//        tickets.add(new ArrayList<String>() {{add("AXA");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("AUA");add("JFK");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("ANU");add("TIA");}});
//        tickets.add(new ArrayList<String>() {{add("AUA");add("JFK");}});
//        tickets.add(new ArrayList<String>() {{add("TIA");add("JFK");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("AUA");}});
//        tickets.add(new ArrayList<String>() {{add("AXA");add("EZE");}});
//        tickets.add(new ArrayList<String>() {{add("AUA");add("ANU");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("AXA");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("AUA");add("ANU");}});
//        tickets.add(new ArrayList<String>() {{add("AXA");add("EZE");}});
//        tickets.add(new ArrayList<String>() {{add("TIA");add("AUA");}});
//        tickets.add(new ArrayList<String>() {{add("AXA");add("EZE");}});
//        tickets.add(new ArrayList<String>() {{add("AUA");add("SYD");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("JFK");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("AUA");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("ANU");}});
//        tickets.add(new ArrayList<String>() {{add("AUA");add("TIA");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("EZE");}});
//        tickets.add(new ArrayList<String>() {{add("TIA");add("JFK");}});
//        tickets.add(new ArrayList<String>() {{add("AXA");add("ANU");}});
//        tickets.add(new ArrayList<String>() {{add("JFK");add("AXA");}});
//        tickets.add(new ArrayList<String>() {{add("JFK");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("EZE");}});
//        tickets.add(new ArrayList<String>() {{add("AXA");add("TIA");}});
//        tickets.add(new ArrayList<String>() {{add("JFK");add("AUA");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("EZE");}});
//        tickets.add(new ArrayList<String>() {{add("JFK");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("AXA");}});
//        tickets.add(new ArrayList<String>() {{add("TIA");add("AUA");}});
//        tickets.add(new ArrayList<String>() {{add("AXA");add("JFK");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("AUA");}});
//        tickets.add(new ArrayList<String>() {{add("TIA");add("JFK");}});
//        tickets.add(new ArrayList<String>() {{add("JFK");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("JFK");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("ANU");add("AXA");}});
//        tickets.add(new ArrayList<String>() {{add("TIA");add("AXA");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("JFK");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("AXA");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("TIA");}});
//        tickets.add(new ArrayList<String>() {{add("JFK");add("AUA");}});
//        tickets.add(new ArrayList<String>() {{add("TIA");add("EZE");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("JFK");add("ANU");}});
//        tickets.add(new ArrayList<String>() {{add("TIA");add("AUA");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("JFK");}});
//        tickets.add(new ArrayList<String>() {{add("ANU");add("AXA");}});
//        tickets.add(new ArrayList<String>() {{add("AUA");add("AXA");}});
//        tickets.add(new ArrayList<String>() {{add("ANU");add("EZE");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("AXA");}});
//        tickets.add(new ArrayList<String>() {{add("ANU");add("AXA");}});
//        tickets.add(new ArrayList<String>() {{add("TIA");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("JFK");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("JFK");add("TIA");}});
//        tickets.add(new ArrayList<String>() {{add("AUA");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("AUA");add("TIA");}});
//        tickets.add(new ArrayList<String>() {{add("TIA");add("JFK");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("JFK");}});
//        tickets.add(new ArrayList<String>() {{add("AUA");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("AUA");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("ANU");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("ANU");}});
//        tickets.add(new ArrayList<String>() {{add("AUA");add("AXA");}});
//        tickets.add(new ArrayList<String>() {{add("AXA");add("TIA");}});
//        tickets.add(new ArrayList<String>() {{add("AXA");add("TIA");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("AXA");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("AXA");}});
//        tickets.add(new ArrayList<String>() {{add("AXA");add("JFK");}});
//        tickets.add(new ArrayList<String>() {{add("JFK");add("AUA");}});
//        tickets.add(new ArrayList<String>() {{add("ANU");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("AXA");add("TIA");}});
//        tickets.add(new ArrayList<String>() {{add("ANU");add("AUA");}});
//        tickets.add(new ArrayList<String>() {{add("JFK");add("EZE");}});
//        tickets.add(new ArrayList<String>() {{add("AXA");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("TIA");add("EZE");}});
//        tickets.add(new ArrayList<String>() {{add("JFK");add("AXA");}});
//        tickets.add(new ArrayList<String>() {{add("AXA");add("ADL");}});
//        tickets.add(new ArrayList<String>() {{add("EZE");add("AUA");}});
//        tickets.add(new ArrayList<String>() {{add("AXA");add("ANU");}});
//        tickets.add(new ArrayList<String>() {{add("ADL");add("EZE");}});
//        tickets.add(new ArrayList<String>() {{add("AUA");add("EZE");}});
        System.out.println(new Solution().findItinerary(tickets));
    }

    static class Solution {
        // 线条方向(利用PriorityQueue来自动排序)
        Map<String, PriorityQueue<String>> map = new HashMap<>();
        // 返回值
        List<String> ret = new ArrayList<>();
        public List<String> findItinerary(List<List<String>> tickets) {
            // 初始化
            for (int i = 0; i < tickets.size(); i++) {
                String from = tickets.get(i).get(0);
                String to = tickets.get(i).get(1);
                if(!map.containsKey(from)) map.put(from, new PriorityQueue<String>());
                map.get(from).offer(to);
            }
            // 搜索
            dfs("JFK");
            return ret;
        }
        private void dfs(String from){
            while (map.containsKey(from) && !map.get(from).isEmpty()){
                dfs(map.get(from).poll());
            }
            ret.add(0, from);
        }
    }

//    static class Solution {
//        private List<List<String>> ret = new ArrayList<>();
//        public List<String> findItinerary(List<List<String>> tickets) {
//            // 索引
//            Stack<Integer> stackIndex = new Stack<>();
//            dfs(tickets, stackIndex);
//            if (ret.isEmpty()) {
//                return null;
//            }
//            ret.sort(Comparator.comparing(o -> o.toString()));
//            return ret.get(0);
//        }
//        //
//        private void dfs(List<List<String>> tickets, Stack<Integer> stackIndex) {
//            System.out.println(stackIndex);
//            if (tickets.size() == stackIndex.size()) {
//                List<String> retlist = new ArrayList<>();
//                for (int i = 0; i < stackIndex.size(); i++) {
//                    Integer index = stackIndex.get(i);
//                    retlist.add(tickets.get(index).get(0));
//                    if (stackIndex.size() == i + 1) retlist.add(tickets.get(index).get(1));
//                }
//                ret.add(retlist);
//            }
//            // 检索key
//            final String key = stackIndex.isEmpty() ? "JFK" : tickets.get(stackIndex.peek()).get(1);
//            // 查找index
//            List<Integer> listIndex = new ArrayList<>();
//            for (int i = 0; i < tickets.size(); i++) {
//                if (stackIndex.contains(i)) continue;
//                if (key.equals(tickets.get(i).get(0))) {
//                    listIndex.add(i);
//                }
//            }
//            for (int i = 0; i < listIndex.size(); i++) {
//                stackIndex.push(listIndex.get(i));
//                dfs(tickets, stackIndex);
//                stackIndex.pop();
//            }
//        }
//    }
}